package sv;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class GraphicsWhindow extends JFrame implements KeyListener{
	private ArrayList[] values = new ArrayList[] { new ArrayList<Long>(),
			new ArrayList<Long>(), new ArrayList<Long>() };
	private Pan p;
	private PanOp po;
	private long[] acVals = new long[3];
	private long scale = 1l;
	private int yT = 12;
	private int sY = 20;
	private int xT = 100;
	private int w = 1024, h = 310, wo = 70, ho = 18;
	private int yZ = 260;
	private int xZ = 35;
	private int sb = 15;
	private float dx = (w - sb - xZ) / (xT * 1.0f);
	private JFrame frame;
	private JSlider sl;

	public GraphicsWhindow() {
		frame = this;
		addKeyListener(this);

		setBounds(0, 700-h, w, h);
		setTitle("Grafici");

		p = new Pan();
		p.setLayout(null);

		po = new PanOp();
		po.setBounds(w - wo, 0, wo, ho);

		JLabel lab = new JLabel("Ritardo(ms):");
		lab.setBounds(w - 475, h - 45, 80, 35);
		sl = new JSlider();
		// sl.setBorder(new TitledBorder("Ritardo"));
		sl.setBounds(w - 405, h - 37, 400, 35);
		sl.setBackground(null);
		sl.setOrientation(JSlider.HORIZONTAL);
		sl.setMajorTickSpacing(100);
		sl.setMaximum(1000);
		sl.setMinimum(0);
		sl.setMinorTickSpacing(1);
		sl.setPaintLabels(true);
		// sl.setPaintTicks(true);
		sl.setPaintTrack(true);
		sl.setSnapToTicks(true);
		sl.setValue(ToolBox.getRit());
		sl.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				ToolBox.setRit(sl.getValue());
			}
		});

		p.add(lab);
		p.add(sl);
		p.add(po);
		add(p);

		setBackground(Color.white);

		setResizable(false);
		setUndecorated(true);
		setAlwaysOnTop(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		requestFocus();
	}
	
	public void changeRit(int rit){
		sl.setValue(rit);
	}

	private int clicX, clicY, tempX, tempY, posX, posY;
	private boolean dragging = false;

	class MouseOnGraph extends MouseAdapter {
		public void mousePressed(MouseEvent me) {
			clicX = me.getX();
			clicY = me.getY();
			tempX = posX;
			tempY = posY;
			dragging = true;
		}
	}

	class MouseMOnGraph extends MouseMotionAdapter{
		public void mouseDragged(MouseEvent me) {
			//System.out.println("dragging");
			if (dragging)
				riposizionaFrame(me.getX() - clicX, me.getY() - clicY);
		}
	}

	private void riposizionaFrame(int x, int y) {
		setLocation(tempX + x, tempY + y);
		tempX += x;
		tempY += y;
		posX += x;
		posY += y;
	}

	class Pan extends JPanel {
		public Pan() {
			addMouseListener(new MouseOnGraph());
			addMouseMotionListener(new MouseMOnGraph());
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			setBackground(Color.white);
			long[] medie = new long[3];

			g.setColor(Color.black);
			g.drawRect(0, 0, w - 1, h - 1);

			g.setColor(new Color(240, 240, 240));
			g.fillRect(xZ, yZ - yT * sY, w - xZ - sb, yT * sY);

			g.setColor(Color.black);
			for (int i = 0; i <= yT; i++) {
				// System.out.println(i);
				g.drawLine(xZ, yZ - i * sY, w - sb, yZ - i * sY);
				String label = "" + (i * sY);
				int ll = label.length();
				g.drawString(label, xZ - 10 * ll, yZ - i * sY + 5);
			}

			g.drawString("x" + scale, 5, 12);
			g.drawString("Grafico", 580, 12);
			
			Font f = g.getFont();
			g.setFont(new Font("TimesRoman",Font.PLAIN,10));

			for (int i = 0; i <= xT / 10; i++) {
				g.drawLine((int) (xZ + i * dx * 10), yZ, (int) (xZ + i * dx
						* 10), yZ - yT * 20);
				if (i > 0)
					g.drawString("" + (i * 10), (int) (xZ + i * dx * 10 - 8),
							yZ + 13);
			}
			
			g.setFont(f);

			for (int i = 0; i < values.length; i++) {
				g.setColor(ToolBox.getColor(i));
				for (int j = 0; j < values[i].size() - 1; j++) {
					long value = (long) ((Long) values[i].get(j));
					long value1 = (long) ((Long) values[i].get(j + 1));
					medie[i] += value + 0l;
					// System.out.println(j);
					g.drawLine((int) (j * dx + xZ), yZ - (int) (value / scale),
							(int) ((j + 1) * dx + xZ), yZ
									- (int) (value1 / scale));
				}
				if (values[i].size() == 0)
					g.drawLine(xZ, yZ - (int) (acVals[i] / scale), xZ, yZ
							- (int) (acVals[i] / scale));
				else {
					int l = values[i].size() - 1;
					long value = (long) ((Long) values[i].get(l));
					medie[i] += value + 0l;
					g.drawLine((int) (l * dx + xZ), yZ - (int) (value / scale),
							(int) ((l + 1) * dx + xZ), yZ
									- (int) (acVals[i] / scale));
				}
				medie[i] += acVals[i] + 0l;
				medie[i] /= (values[i].size() + 1l);
				g.drawLine(xZ, yZ - (int) (medie[i] / scale), w - sb, yZ
						- (int) (medie[i] / scale));
				g.drawString("Solver" + (i + 1) + ":" + medie[i], xZ, yZ + 13
						+ 10 * (i + 1));
			}
		}
	}

	class PanOp extends JPanel {
		private int we = 70;

		public PanOp() {
			addMouseListener(new Mouse());
			addMouseMotionListener(new MouseM());
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2 = (Graphics2D) g;

			// setBackground(Color.white);
			setBackground(Color.white);

			g2.setColor(Color.gray);

			g2.fill(new Rectangle(we / 2, 0, wo - we / 2, ho));

			Ellipse2D e1 = new Ellipse2D.Double(we / 4, 0, we * 3 / 4, ho);
			g2.fill(e1);

			Area eS1 = new Area(e1);
			Area eS2 = new Area(
					new Ellipse2D.Double(-we / 2, 0, we * 3 / 4, ho));
			eS2.add(eS1);

			Area r = new Area(new Rectangle(0, 0, we / 2, ho / 2));
			r.subtract(eS2);
			g2.fill(r);

			// ridurre a icona
			g2.setColor(Color.blue);
			g2.drawRect(we / 2, 2, 15, ho - 4);
			g2.setColor(Color.white);
			g2.setStroke(new BasicStroke(2));
			g2.drawLine(we / 2 + 3, ho - 5, we / 2 + 12, ho - 5);
			g2.setStroke(new BasicStroke(1));

			// chiudere
			g.setColor(Color.red);
			g.fillRect(we / 2 + 17, 2, 15, ho - 4);
			g.setColor(Color.white);
			g.drawString("x", we / 2 + 22, ho - 5);
		}

		class Mouse extends MouseAdapter {
			public void mousePressed(MouseEvent ev) {
				int xC = (int) ev.getX();
				int yC = (int) ev.getY();

				if (xC > we / 2 && xC < (we / 2 + 15) && yC > 2
						&& yC < (ho - 4)) {
					iconify();
				}
				if (xC > (we / 2 + 17) && xC < (we / 2 + 32) && yC > 2
						&& yC < (ho - 4)) {
					exit();
				}
			}
		}

		class MouseM extends MouseMotionAdapter {
			public void mouseMoved(MouseEvent ev) {
				int xC = (int) ev.getX();
				int yC = (int) ev.getY();

				boolean ic = xC > we / 2 && xC < (we / 2 + 15) && yC > 2
						&& yC < (ho - 4);
				boolean exi = xC > (we / 2 + 17) && xC < (we / 2 + 32)
						&& yC > 2 && yC < (ho - 4);

				if (ic || exi)
					setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
				else
					setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			}
		}
	}

	public void iconify() {
		int state = frame.getExtendedState();

		// Set the iconified bit
		state = JFrame.ICONIFIED;

		// Iconify the frame
		frame.setExtendedState(state);
	}

	public void exit() {
		//System.exit(0);
		ToolBox.closeTest();
	}

	public void addValue(int i, long value) {
		// System.out.println(i+ " " + value);
		values[i].add(value);
		acVals[i] = 0;
		if (xT != SudokuGames.total() - 1 && values[i].size() > xT) {
			xT += 50;
			dx = (w - sb - xZ) / (xT * 1.0f);
			if (dx < 1)
				dx = 1;
		}
		repaint();
	}

	private int[] agg = new int[3];

	public void addAcValue(int i, long value) {
		// System.out.println(i+ " " + value);
		acVals[i] = value;
		agg[i]++;
		if (value > yT * sY * scale) {
			scale *= 2l;
			agg = new int[3];
			repaint();
		}
		if (agg[i] >= scale) {
			agg[i] = 0;
			repaint();
		}
	}
	
	public void keyPressed(KeyEvent e){
		int codice = e.getKeyCode();
		String tasto = e.getKeyText(codice);
		ToolBox.setDelay(tasto);
	}
	
	public void keyReleased(KeyEvent e){}
	public void keyTyped(KeyEvent e){}
}

class TestGraph {
	public static void main(String[] args) {
		GraphicsWhindow gWindow = new GraphicsWhindow();
		for (int i = 0; i < 100; i++) {
			gWindow.addValue(0, i);
		}
		for (int i = 1; i < 100; i *= 2) {
			gWindow.addValue(1, i);
		}
		for (int i = 1; i < 100; i *= 3) {
			gWindow.addValue(2, i);
		}
	}
}
